package com.codemeta.bokit.comm.kit;

import static cn.hutool.core.text.CharSequenceUtil.isBlankOrUndefined;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import com.codemeta.bokit.comm.global.DefaultErrorCode;
import com.codemeta.bokit.comm.global.ErrorCode;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * Optional工具类
 *
 * @author 美萌:hechen
 * @date 2020/1/16
 */
public class OptKit {

    /**
     * NPE为空初始化
     *
     * @param t   .
     * @param e   .
     * @param <T> .
     * @return .
     */
    public static <T> T orElse(T t, T e) {
        return Optional.ofNullable(t).orElse(e);
    }

    /**
     * java1.9 ifPresentOrElse 实现
     *
     * @param value    对象
     * @param consumer if函数
     * @param runnable else函数
     * @param <T>      泛型
     */
    public static <T> void present(T value, Consumer<? super T> consumer, Runnable runnable) {
        if (value != null) {
            consumer.accept(value);
        } else if (runnable != null) {
            runnable.run();
        }
    }

    public static <T> void present(T value, Consumer<? super T> consumer) {
        present(value, consumer, null);
    }

    /**
     * 获取NPE对象或抛出异常
     *
     * @param t   对象
     * @param msg 异常信息
     * @param <T> 泛型
     * @return 对象
     */
    public static <T> T error(T t, String msg) {
        return Optional.ofNullable(t)
            .orElseThrow(() -> ExceptionKit.exception(DefaultErrorCode.params, msg));
    }

    /**
     * 获取NPE对象或抛出异常
     *
     * @param t     对象
     * @param error 错误码对象
     * @param <T>   泛型
     * @return 对象
     */
    public static <T> T error(T t, ErrorCode error) {
        return Optional.ofNullable(t).orElseThrow(() -> ExceptionKit.exception(error));
    }

    /**
     * 集合为空时异常
     *
     * @param coll .
     * @param msg  .
     */
    public static <T> void error(Collection<T> coll, String msg) {
        if (coll == null || coll.isEmpty()) {
            throw ExceptionKit.exception(DefaultErrorCode.params, msg);
        }
    }

    /**
     * null|false时异常
     *
     * @param bol .
     * @param msg .
     */
    public static void error(Boolean bol, String msg) {
        if (BooleanUtil.isFalse(bol)) {
            throw ExceptionKit.exception(DefaultErrorCode.param, msg);
        }
    }

    /**
     * 字符串为空时异常
     *
     * @param str .
     * @param msg .
     */
    public static void error(String str, String msg) {
        if (isBlankOrUndefined(str)) {
            throw ExceptionKit.exception(DefaultErrorCode.param, msg);
        }
    }

    /**
     * number为空时异常
     *
     * @param num .
     * @param msg .
     */
    public static void error(Number num, String msg) {
        if (NumKit.gt0(num)) {
            throw ExceptionKit.exception(DefaultErrorCode.param, msg);
        }
    }

    /**
     * 字符串不为空时执行
     *
     * @param str      .
     * @param consumer 不为空执行
     * @param runnable 为空执行
     */
    public static void str(String str, Consumer<String> consumer, Runnable runnable) {
        if (!isBlankOrUndefined(str)) {
            consumer.accept(str);
        } else if (runnable != null) {
            runnable.run();
        }
    }

    public static void str(String str, Consumer<String> consumer) {
        str(str, consumer, null);
    }

    public static void blank(String str, Runnable runnable) {
        if (isBlankOrUndefined(str) && runnable != null) {
            runnable.run();
        }
    }

    /**
     * 集合不为空时执行
     *
     * @param coll     .
     * @param consumer .
     * @param <T>      .
     */
    public static <T> void coll(Collection<T> coll, Consumer<Collection<T>> consumer, Runnable runnable) {
        if (CollUtil.isNotEmpty(coll) && consumer != null) {
            consumer.accept(coll);
        } else if (runnable != null) {
            runnable.run();
        }
    }

    public static <T> void coll(Collection<T> coll, Consumer<Collection<T>> consumer) {
        coll(coll, consumer, null);
    }

    public static <T> void empty(Collection<T> coll, Consumer<Collection<T>> consumer) {
        if (CollUtil.isEmpty(coll) && consumer != null) {
            consumer.accept(coll);
        }
    }

    /**
     * 当 intVal >= 0 时执行consumer，否则执行runnable
     *
     * @param intVal   .
     * @param consumer .
     * @param runnable .
     */
    public static <T extends Number> void ge0(T intVal, Consumer<T> consumer, Runnable runnable) {
        if (NumKit.gt0(intVal)) {
            consumer.accept(intVal);
        } else if (runnable != null) {
            runnable.run();
        }
    }

    public static <T extends Number> void ge0(T intVal, Consumer<T> consumer) {
        ge0(intVal, consumer, null);
    }

    /**
     * 当 intVal <= 0 时则执行runnable
     *
     * @param intVal   .
     * @param runnable .
     */
    public static <T extends Number> void le0(T intVal, Runnable runnable) {
        if (NumKit.le0(intVal) && runnable != null) {
            runnable.run();
        }
    }
}